package org.noote.libs.sogle.helper;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.noote.libs.sogle.Material;
import org.noote.libs.sogle.Mesh;
import org.noote.libs.sogle.Object3D;
import org.noote.libs.sogle.Object3D_Group;

public class SimpleMeshFormat_Loader {

	static public Mesh loadAsMesh(InputStream fis, Material mat)
	{
		Mesh mesh=null;
		float[] vertices = null;
		short[] indices = null;
		
		final int MODE_HEADER=0, MODE_OBJECT_COUNT=1, MODE_OBJECT_NAME=2, MODE_VERTEX_COUNT=3, MODE_VERTEX_DEF=4, MODE_FACE_COUNT=5, MODE_FACE_DEF=6, MODE_END=7;
		int mode = MODE_HEADER;
		int inc_vertex = 0, inc_face=0;
		int iVertex = 0, iFace=0;
		String sLine;
		InputStreamReader isr = new InputStreamReader(fis);
		BufferedReader reader = new BufferedReader(isr, 1024);
		try {
			
			while (mode!=MODE_END && (sLine = reader.readLine()) != null) {
				sLine = sLine.trim();
				if (sLine.length() > 0) {

					switch( mode )
					{
						case MODE_HEADER:
						{
							String sSplit[] = sLine.split("\\ ");
							if(sSplit.length != 2) return null;
							if(!sSplit[0].equalsIgnoreCase("SimpleMeshFormat") || !sSplit[1].equalsIgnoreCase("1")) return null;
							mesh = new Mesh();
							mode++;
							break;
						}
						case MODE_OBJECT_COUNT:
						{
							// no more than 1 object, please ^^
							if(!sLine.equalsIgnoreCase("1")) return null;
							mode++;
							break;
						}
						case MODE_OBJECT_NAME:
						{
							// no need a name... skip
							mode++;
							break;
						}
						case MODE_VERTEX_COUNT:
						{
							iVertex = Integer.parseInt(sLine);
							if(iVertex <= 0) return null;
							vertices = new float [iVertex*3];
							inc_vertex=0;
							mode++;
							break;
						}
						case MODE_VERTEX_DEF:
						{
							String sSplit[] = sLine.split("\\ ");
							if(sSplit.length != 3)
								return null;

							vertices[(inc_vertex*3)+0] = Float.parseFloat(sSplit[0]);
							vertices[(inc_vertex*3)+1] = Float.parseFloat(sSplit[1]);
							vertices[(inc_vertex*3)+2] = Float.parseFloat(sSplit[2]);
							
							inc_vertex++;
							if(inc_vertex == iVertex)
								mode++;
							
							break;
						}
						case MODE_FACE_COUNT:
						{
							iFace = Integer.parseInt(sLine);
							if(iFace <= 0) return null;
							indices = new short [iFace*3];
							inc_face=0;
							mode++;
							break;
						}
						case MODE_FACE_DEF:
						{
							String sSplit[] = sLine.split("\\ ");
							if(sSplit.length != 19) return null;

							indices[(inc_face*3)+0] = Short.parseShort(sSplit[1]);
							indices[(inc_face*3)+1] = Short.parseShort(sSplit[2]);
							indices[(inc_face*3)+2] = Short.parseShort(sSplit[3]);
							
							inc_face++;
							if(inc_face == iFace)
								mode++;
							
							break;
						}
					}
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
		if(mesh != null)
		{
			mesh.getMaterial().set(mat);
			mesh.setVertices(vertices);
			mesh.setIndices(indices);
			mesh.generateNormales();
		}
		
		return mesh;
	}


	static public Object3D load(InputStream fis)
	{
		Object3D_Group group = null;
		Mesh mesh = null;
		float[] vertices = null;
		short[] indices = null;
		
		final int MODE_HEADER=0, MODE_OBJECT_COUNT=1, MODE_OBJECT_NAME=2, MODE_VERTEX_COUNT=3, MODE_VERTEX_DEF=4, MODE_FACE_COUNT=5, MODE_FACE_DEF=6, MODE_END=7;
		int mode = MODE_HEADER;
		int inc_mesh = 0, inc_vertex = 0, inc_face=0;
		int iMesh = 0, iVertex = 0, iFace=0;
		String sLine;
		InputStreamReader isr = new InputStreamReader(fis);
		BufferedReader reader = new BufferedReader(isr, 1024);
		try {
			
			while (mode!=MODE_END && (sLine = reader.readLine()) != null) {
				sLine = sLine.trim();
				if (sLine.length() > 0) {

					switch( mode )
					{
						case MODE_HEADER:
						{
							String sSplit[] = sLine.split("\\ ");
							if(sSplit.length != 2) return null;
							if(!sSplit[0].equalsIgnoreCase("SimpleMeshFormat") || !sSplit[1].equalsIgnoreCase("1")) return null;
							group = new Object3D_Group();
							mode++;
							break;
						}
						case MODE_OBJECT_COUNT:
						{
							iMesh = Integer.parseInt(sLine);
							if(iMesh<=0) return null;
							inc_mesh = 0;
							mode++;
							break;
						}
						case MODE_OBJECT_NAME:
						{
							inc_mesh++;
							if(inc_mesh == iMesh+1)
							{
								mode=MODE_END;
								break;
							}
							
							mode++;
							break;
						}
						case MODE_VERTEX_COUNT:
						{
							iVertex = Integer.parseInt(sLine);
							if(iVertex <= 0) return null;
							vertices = new float [iVertex*3];
							inc_vertex=0;
							mode++;
							break;
						}
						case MODE_VERTEX_DEF:
						{
							String sSplit[] = sLine.split("\\ ");
							if(sSplit.length != 3)
								return null;

							vertices[(inc_vertex*3)+0] = Float.parseFloat(sSplit[0]);
							vertices[(inc_vertex*3)+1] = Float.parseFloat(sSplit[1]);
							vertices[(inc_vertex*3)+2] = Float.parseFloat(sSplit[2]);
							
							inc_vertex++;
							if(inc_vertex == iVertex)
								mode++;
							
							break;
						}
						case MODE_FACE_COUNT:
						{
							iFace = Integer.parseInt(sLine);
							if(iFace <= 0) return null;
							indices = new short [iFace*3];
							inc_face=0;
							mode++;
							break;
						}
						case MODE_FACE_DEF:
						{
							String sSplit[] = sLine.split("\\ ");
							if(sSplit.length != 19) return null;

							indices[(inc_face*3)+0] = Short.parseShort(sSplit[1]);
							indices[(inc_face*3)+1] = Short.parseShort(sSplit[2]);
							indices[(inc_face*3)+2] = Short.parseShort(sSplit[3]);
							
							inc_face++;
							if(inc_face == iFace)
							{
								mesh = new Mesh();
								
								mesh.setVertices(vertices);
								mesh.setIndices(indices);
								mesh.generateNormales();
								
								group.add(mesh);
							
								mode=MODE_OBJECT_NAME;
							}
							
							break;
						}
					}
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
		return group;
	}
}
